﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;

namespace WindowsFormsApplication6
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        System.ComponentModel.BindingList<Sync.Library.Server> Servers = new BindingList<Sync.Library.Server>();

        string xmlSyncLayout = "";
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                LoadServers();
                //lbTableNames.DisplayMember = "Name";
                //lbTableNames.ValueMember = "Selected";
                //Sync.Library.SyncServers servers = Sync.Library.SyncServers.GetSyncServers();

                DevExpress.XtraGrid.Columns.GridColumn colServerName = new DevExpress.XtraGrid.Columns.GridColumn();
                colServerName.Visible = true;
                colServerName.VisibleIndex = 0;
                colServerName.Width = 40;
                colServerName.FieldName = "Description";
                colServerName.Name = "colServerName";
                viewServers.Columns.Add(colServerName);

                gridServers.DataSource = Servers;

                DevExpress.XtraGrid.Columns.GridColumn colSelected = new DevExpress.XtraGrid.Columns.GridColumn();
                colSelected.Visible = true;
                colSelected.VisibleIndex = 0;
                colSelected.Width = 40;
                colSelected.FieldName = "Selected";
                colSelected.Name = "colSelected";
                viewTables.Columns.Add(colSelected);

                DevExpress.XtraGrid.Columns.GridColumn colName = new DevExpress.XtraGrid.Columns.GridColumn();
                colName.Visible = true;
                colName.VisibleIndex = 1;
                colName.Width = 120;
                colName.FieldName = "Name";
                colName.Name = "colName";
                viewTables.Columns.Add(colName);

                DevExpress.XtraGrid.Columns.GridColumn colRemoteName = new DevExpress.XtraGrid.Columns.GridColumn();
                colRemoteName.Visible = true;
                colRemoteName.VisibleIndex = 2;
                colRemoteName.Width = 120;
                colRemoteName.FieldName = "RemoteName";
                colRemoteName.Name = "colRemoteName";
                viewTables.Columns.Add(colRemoteName);

                gridTables.DataSource = Sync.Library.Tables.GetTables();
                //gridTables.DataBindings.Add("DataSource", gridServers.DataSource, "Tables");

                //lbColumns.DisplayMember = "Name";
                //lbColumns.ValueMember = "Selected";

                colSelected = new DevExpress.XtraGrid.Columns.GridColumn();
                colSelected.Visible = true;
                colSelected.VisibleIndex = 0;
                colSelected.Width = 40;
                colSelected.FieldName = "Selected";
                colSelected.Name = "colSelected";
                viewColumns.Columns.Add(colSelected);

                colName = new DevExpress.XtraGrid.Columns.GridColumn();
                colName.Visible = true;
                colName.VisibleIndex = 1;
                colName.Width = 120;
                colName.FieldName = "Name";
                colName.Name = "colName";
                viewColumns.Columns.Add(colName);

                colRemoteName = new DevExpress.XtraGrid.Columns.GridColumn();
                colRemoteName.Visible = true;
                colRemoteName.VisibleIndex = 2;
                colRemoteName.Width = 120;
                colRemoteName.FieldName = "RemoteName";
                colRemoteName.Name = "colRemoteName";
                viewColumns.Columns.Add(colRemoteName);

                gridColumns.DataBindings.Add("DataSource", gridTables.DataSource, "Columns");

                gridServers.BindingContext[gridServers.DataSource].CurrentChanged += new EventHandler(Form1_CurrentChanged);
                

                viewTables.CellValueChanged += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(viewTables_CellValueChanged);
                viewColumns.CellValueChanged += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(viewColumns_CellValueChanged);

                if (Servers.Count > 0)
                    LoadCheckedTables(Servers[0].Tables);
            }
            catch (Exception ex)
            {
            }
        }

        private void LoadServers()
        {            
            Sync.Library.SyncInfo syncInfo = Sync.Library.SyncInfo.GetSyncInfo();
            if (syncInfo.ID == 0)
              return;

            string xml = syncInfo.Xml;

            System.Xml.Linq.XDocument d = System.Xml.Linq.XDocument.Parse(xml);

            var servers = from i in d.Element("Servers").Descendants("Server") select i;

            foreach (var server in servers)
            {
                Sync.Library.Server serv = new Sync.Library.Server();
                serv.Description = server.Attribute("Description").Value;
                serv.IP = server.Attribute("IP").Value;
                serv.Port = server.Attribute("Port").Value;
                serv.InstanceName = server.Attribute("InstanceName").Value;
                serv.UserID = server.Attribute("UserID").Value;
                serv.Password = server.Attribute("Password").Value;
                serv.DBName = server.Attribute("DBName").Value;

                var tables = from i in server.Element("Tables").Descendants("Table") select i;

                foreach (var table in tables)
                {
                    Sync.Library.Table tbl = new Sync.Library.Table("");
                    tbl.Name = table.Attribute("Name").Value;
                    tbl.RemoteName = table.Attribute("RemoteName").Value;

                    var columns = from i in table.Descendants("Column") select i;
                    foreach (var column in columns)
                    {
                        Sync.Library.Column col = new Sync.Library.Column("", "");
                        col.Name = column.Attribute("Name").Value;
                        col.RemoteName = column.Attribute("RemoteName").Value;

                        tbl.Columns.Add(col);
                    }

                    serv.Tables.Add(tbl);
                }

                Servers.Add(serv);
            }
        }

        void viewColumns_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (e.Column.FieldName == "Selected")
            {
                Sync.Library.Server server = (Sync.Library.Server)viewServers.GetRow(viewServers.FocusedRowHandle);
                Sync.Library.Column column = (Sync.Library.Column)viewColumns.GetRow(e.RowHandle);
                Sync.Library.Table table = (Sync.Library.Table)viewTables.GetRow(viewTables.FocusedRowHandle);

                if (((bool)e.Value) == true)
                {
                    var t = (from i in server.Tables where i.Name == table.Name select i).FirstOrDefault();
                    var a = (from i in t.Columns where i.Name == column.Name select i).FirstOrDefault();

                    if (a == null)
                    {
                        Sync.Library.Column c = new Sync.Library.Column(column.Name, "");
                        c.Name = column.Name;
                        c.RemoteName = column.RemoteName;
                        c.Selected = true;
                        t.Columns.Add(c);
                    }
                }
            }
        }

        void viewTables_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (e.Column.FieldName == "Selected")
            {
                Sync.Library.Table table = (Sync.Library.Table)viewTables.GetRow(e.RowHandle);
                Sync.Library.Server server = (Sync.Library.Server)viewServers.GetRow(viewServers.FocusedRowHandle);
                if (((bool)e.Value) == true)
                {
                    var a = (from i in server.Tables where i.Name == table.Name select i).FirstOrDefault();
                    if (a == null)
                    {
                        Sync.Library.Table t = new Sync.Library.Table(table.Name);
                        t.Name = table.Name;
                        t.RemoteName = table.RemoteName;
                        t.Selected = true;

                        var cols = from i in table.Columns where i.Selected == true select i;
                        if (cols.Count() > 0)
                        {
                            foreach (Sync.Library.Column col in cols)
                            {
                                Sync.Library.Column c = new Sync.Library.Column(col.Name, "");
                                c.Name = col.Name;
                                c.RemoteName = col.RemoteName;
                                c.Selected = true;
                                t.Columns.Add(c);
                            }
                        }

                        server.Tables.Add(t);
                    }
                }
            }
        }

        void Form1_CurrentChanged(object sender, EventArgs e)
        {
            Sync.Library.Server currentServer = (Sync.Library.Server)gridServers.BindingContext[gridServers.DataSource].Current;
            if (currentServer == null)
                return;
            LoadCheckedTables(currentServer.Tables);
            ((Sync.Library.Tables)gridTables.DataSource).Server = currentServer;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                string scopeName = "Areas1";

                foreach (Sync.Library.Server server in Servers)
                {
                    string remoteConnString = CreateConnectionString(server);

                    Provider p = new Provider();
                    p.TablesToSync = server.Tables;

                    //p.ConfigureScope("katalun4o-pc", "RetailMain", scopeName);
                    p.ConfigureScope(Sync.Library.Settings.ConnStringMain, scopeName);

                    //p.ConfigureScope("katalun4o-pc", "RetailRemote", scopeName);
                    //p.ConfigureScope(Sync.Library.Settings.ConnStringRemote, scopeName);
                    p.ConfigureScope(remoteConnString, scopeName);

                    //Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerLocal = p.ConfigureSqlSyncProvider("katalun4o-pc", "RetailMain",scopeName);
                    Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerLocal = p.ConfigureSqlSyncProvider(Sync.Library.Settings.ConnStringMain, scopeName);

                    //Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerRemote = p.ConfigureSqlSyncProvider("katalun4o-pc", "RetailRemote", scopeName);
                    //Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerRemote = p.ConfigureSqlSyncProvider(Sync.Library.Settings.ConnStringRemote, scopeName);
                    
                    Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerRemote = p.ConfigureSqlSyncProvider(remoteConnString, scopeName);

                    SyncOrchestrator orchestrator = new SyncOrchestrator();
                    orchestrator.LocalProvider = providerLocal;
                    orchestrator.RemoteProvider = providerRemote;
                    orchestrator.Direction = SyncDirectionOrder.DownloadAndUpload;
                    orchestrator.Synchronize();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private string CreateConnectionString(Sync.Library.Server server)
        {
            System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
            builder.UserID = server.UserID;
            builder.Password = server.Password;
            builder.InitialCatalog = server.DBName;
            if(server.Port != "")
                builder.DataSource = server.IP + ":" + server.Port + "\\" + server.InstanceName;
            else
                builder.DataSource = server.IP + "\\" + server.InstanceName;
            return builder.ToString();
        }

        private void btnSync_Click(object sender, EventArgs e)
        {
            Provider p = new Provider();

            string scopeName = "Areas1";

            //Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerLocal = p.ConfigureSqlSyncProvider("katalun4o-pc", "RetailMain", scopeName);
            //Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerRemote = p.ConfigureSqlSyncProvider("katalun4o-pc", "RetailRemote", scopeName);

            Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerLocal = p.ConfigureSqlSyncProvider(Sync.Library.Settings.ConnStringMain, scopeName);
            Microsoft.Synchronization.Data.SqlServer.SqlSyncProvider providerRemote = p.ConfigureSqlSyncProvider(Sync.Library.Settings.ConnStringRemote, scopeName);

            foreach (Sync.Library.Server serv in Servers)
            {
                CustomProvider prov = new CustomProvider(scopeName, serv.Tables);

                SyncOrchestrator orchestrator = new SyncOrchestrator();
                //orchestrator.LocalProvider = providerLocal;
                orchestrator.LocalProvider = prov;
                orchestrator.RemoteProvider = providerRemote;
                orchestrator.Direction = SyncDirectionOrder.DownloadAndUpload;
                orchestrator.Synchronize();
            }
        }

        private void lbTableNames_SelectedIndexChanged(object sender, EventArgs e)
        {
            //string currentTable = lbTableNames.SelectedItem.ToString();
            //lbColumns.DataSource = Sync.Library.Column.GetColumns(currentTable);
        }

        //Sync.Library.Tables TablesToSync;
        private void button2_Click(object sender, EventArgs e)
        {
            //choose columns
            /*foreach (string s in gridco.SelectedItems)
            {
                string tableName = lbTableNames.SelectedItem.ToString();
                Sync.Library.Table table = (from i in TablesToSync where i.Name == tableName select i).FirstOrDefault<Sync.Library.Table>();
                if (table == null)
                {
                    table = new Sync.Library.Table(tableName);
                    TablesToSync.Add(table);
                }
            }
            */
        }

        private void LoadCheckedTables(Sync.Library.Tables tables)
        {
            foreach (Sync.Library.Table tbl in (Sync.Library.Tables)gridTables.DataSource)
            {
                tbl.Selected = false;
            }

            foreach (Sync.Library.Column col in (Sync.Library.Columns)gridColumns.DataSource)
            {
                col.Selected = !col.IsNullable;
            }
            //Sync.Library.SyncInfo syncInfo = Sync.Library.SyncInfo.GetSyncInfo();
            //if (syncInfo.ID == 0)
              //  return;

            //string xml = syncInfo.Xml;

            //System.Xml.Linq.XDocument d = System.Xml.Linq.XDocument.Parse(xml);
            //var tables = d.Element("Tables").Elements("Table");
            foreach (var table in tables)
            {
                //var x = (from i in ((Sync.Library.Tables)gridTables.DataSource) where i.Name == table.Attribute("Name").Value select i).FirstOrDefault();
                var x = (from i in ((Sync.Library.Tables)gridTables.DataSource) where i.Name == table.Name select i).FirstOrDefault();
                x.Selected = true;

                //var columns = table.Elements("Column");
                var columns = table.Columns;
                foreach (var column in columns)
                {
                    //var y = (from i in x.Columns where i.Name == column.Attribute("Name").Value select i).FirstOrDefault();
                    var y = (from i in x.Columns where i.Name == column.Name select i).FirstOrDefault();
                    y.Selected = true;
                }
            }

            /*Sync.Library.SyncServers servers = (Sync.Library.SyncServers)gridServers.DataSource;
            foreach (Sync.Library.SyncServer server in servers)
            {
                foreach (Sync.Library.SyncTable table in server.SyncTables)
                {
                    var x = (from i in ((Sync.Library.Tables)gridTables.DataSource) where i.Name == table.TableName select i).FirstOrDefault();
                    x.Selected = true;

                    foreach (Sync.Library.SyncColumn column in table.SyncColumns)
                    {
                        var y = (from i in x.Columns where i.Name == column.ColumnName select i).FirstOrDefault();
                        y.Selected = true;
                    }
                }
            }*/
            gridTables.RefreshDataSource();
            gridColumns.RefreshDataSource();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            System.Xml.Linq.XDocument d = new System.Xml.Linq.XDocument();

            d.Add(new System.Xml.Linq.XElement("Servers"));

            foreach (Sync.Library.Server s in Servers)
            {
                System.Xml.Linq.XElement serverElement = new System.Xml.Linq.XElement("Server");
                System.Xml.Linq.XAttribute serverDescAttribute = new System.Xml.Linq.XAttribute("Description", s.Description);
                System.Xml.Linq.XAttribute serverIPAttribute = new System.Xml.Linq.XAttribute("IP", s.IP);
                System.Xml.Linq.XAttribute serverPortAttribute = new System.Xml.Linq.XAttribute("Port", s.Port);
                System.Xml.Linq.XAttribute serverInstanceAttribute = new System.Xml.Linq.XAttribute("InstanceName", s.InstanceName);
                System.Xml.Linq.XAttribute serverUserIDAttribute = new System.Xml.Linq.XAttribute("UserID", s.UserID);
                System.Xml.Linq.XAttribute serverPasswordAttribute = new System.Xml.Linq.XAttribute("Password", s.Password);
                System.Xml.Linq.XAttribute serverDBNameAttribute = new System.Xml.Linq.XAttribute("DBName", s.DBName);
                serverElement.Add(serverDescAttribute);
                serverElement.Add(serverIPAttribute);
                serverElement.Add(serverPortAttribute);
                serverElement.Add(serverInstanceAttribute);
                serverElement.Add(serverUserIDAttribute);
                serverElement.Add(serverPasswordAttribute);
                serverElement.Add(serverDBNameAttribute);
                serverElement.Add(new System.Xml.Linq.XElement("Tables"));

                foreach (var table in s.Tables)
                {
                    System.Xml.Linq.XElement tableElement = new System.Xml.Linq.XElement("Table");
                    System.Xml.Linq.XAttribute tableNameAttribute = new System.Xml.Linq.XAttribute("Name", table.Name);
                    System.Xml.Linq.XAttribute tableRemoteNameAttribute = new System.Xml.Linq.XAttribute("RemoteName", table.RemoteName);
                    tableElement.Add(tableNameAttribute);
                    tableElement.Add(tableRemoteNameAttribute);

                    foreach (var col in table.Columns)
                    {
                        if (col.Selected == false)
                            continue;
                        System.Xml.Linq.XElement elColumn = new System.Xml.Linq.XElement("Column");
                        System.Xml.Linq.XAttribute columnNameAttribute = new System.Xml.Linq.XAttribute("Name", col.Name);
                        System.Xml.Linq.XAttribute columnRemoteNameAttribute = new System.Xml.Linq.XAttribute("RemoteName", col.RemoteName);
                        elColumn.Add(columnNameAttribute);
                        elColumn.Add(columnRemoteNameAttribute);
                        tableElement.Add(elColumn);
                    }
                    serverElement.Element("Tables").Add(tableElement);

                }

                d.Element("Servers").Add(serverElement);
            }

            string xmlToSave = d.ToString();

            Sync.Library.SyncInfo syncInfo = Sync.Library.SyncInfo.GetSyncInfo();
            if (syncInfo.ID == 0)
                syncInfo = Sync.Library.SyncInfo.NewSyncInfo();
            syncInfo.Xml = xmlToSave;
            syncInfo.Save();

        }

        private void btnAddServer_Click(object sender, EventArgs e)
        {
            AddServerScreen screen = new AddServerScreen();
            if (screen.ShowDialog() == DialogResult.OK)
            {
                ((System.ComponentModel.BindingList<Sync.Library.Server>)gridServers.DataSource).Add(screen.Server);
            }
        }

        private void btnDeleteServer_Click(object sender, EventArgs e)
        {
            Sync.Library.Server server = (Sync.Library.Server)viewServers.GetRow(viewServers.FocusedRowHandle);
            Servers.Remove(server);
            gridServers.RefreshDataSource();
            LoadCheckedTables(new Sync.Library.Tables());
        }

    }
}
